﻿using System;
using System.Linq;
using System.Security.Principal;
using BLL.Security;

namespace Web.Infrastructure.Security
{
    /// <summary>
    /// Implements <see cref="IPrincipal"/> in a web-specific way.
    /// </summary>
    /// <remarks>
    /// This implementation allows separate storage of front-end, back-end and system authentication
    /// information so that user can be logged in on all three levels in the same browser window.
    /// </remarks>
    public class MultilevelPrincipal : IPrincipal
    {
        private static readonly WebIdentity _anonymousIdentity =
            new WebIdentity(UserTypes.Anonymous.ToString(), false);

        /// <summary>
        /// Initializes a new instance of the <see cref="MultilevelPrincipal"/> class.
        /// </summary>
        internal MultilevelPrincipal()
        {
            Identity = _anonymousIdentity;
            AdministratorIdentity = _anonymousIdentity;
            SystemIdentity = _anonymousIdentity;
        }

        /// <summary>
        /// Gets the administrative suite identity of the current principal.
        /// </summary>
        public IIdentity AdministratorIdentity { get; internal set; }

        /// <summary>
        /// Gets the front-end identity of the current principal.
        /// </summary>
        public IIdentity Identity { get; internal set; }

        /// <summary>
        /// Gets the system identity of the current principal.
        /// </summary>
        public IIdentity SystemIdentity { get; internal set; }

        internal UserRoles Roles { get; set; }

        /// <summary>
        /// Determines whether the current principal belongs to the specified role.
        /// </summary>
        /// <param name="role">The name of the role for which to check membership.</param>
        /// <returns>
        /// <see langword="true"/> if the current principal is a member of the specified role;
        /// otherwise, <see langword="false"/>.
        /// </returns>
        public bool IsInRole(string role)
        {
            return (Roles & (UserRoles)Enum.Parse(typeof(UserRoles), role)) > 0;
        }
    }
}